package com.wll.ppjoke.ui.publish;

import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.ContentValues;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.ImageFormat;
import android.media.MediaScannerConnection;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Looper;
import android.provider.MediaStore;
import android.text.TextUtils;
import android.util.Log;
import android.util.Rational;
import android.util.Size;
import android.view.OrientationEventListener;
import android.view.Surface;
import android.view.TextureView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.camera.core.CameraControl;
import androidx.camera.core.CameraInfo;
import androidx.camera.core.CameraInfoUnavailableException;
import androidx.camera.core.CameraX;
import androidx.camera.core.ImageAnalysis;
import androidx.camera.core.ImageCapture;
import androidx.camera.core.ImageCaptureConfig;
import androidx.camera.core.ImageProxy;
import androidx.camera.core.Preview;
import androidx.camera.core.PreviewConfig;
import androidx.camera.core.UseCase;
import androidx.camera.core.VideoCapture;
import androidx.camera.core.VideoCaptureConfig;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.databinding.DataBindingUtil;

import com.google.common.util.concurrent.ListenableFuture;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.PlanarYUVLuminanceSource;
import com.google.zxing.Result;
import com.google.zxing.common.HybridBinarizer;
import com.wll.ppjoke.R;
import com.wll.ppjoke.databinding.ActivityLayoutCaptureBinding;
import com.wll.ppjoke.model.CameraConfig;
import com.wll.libcommon.utils.DecodeCodeTools;
import com.wll.libcommon.utils.StringUtils;
import com.wll.ppjoke.utils.MediaStoreUtils;
import com.wll.ppjoke.utils.ToastUtils;
import com.wll.ppjoke.view.RecordView;

import java.io.File;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;

import com.wll.ppjoke.ui.Constant;

public class CaptureActivity extends AppCompatActivity {
    private ActivityLayoutCaptureBinding mBinding;
    private static final String[] PERMISSIONS = new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.RECORD_AUDIO};
    private static final int PERMISSION_CODE = 1000;
    private ArrayList<String> deniedPermission = new ArrayList<>();
    private CameraX.LensFacing mLensFacing = CameraX.LensFacing.BACK;
    private int rotation = Surface.ROTATION_0;
    private Size resolution = new Size(1280, 720);
    private Rational rational = new Rational(9, 16);
    private Preview preview;
    private ImageCapture imageCapture;
    private VideoCapture videoCapture;
    private TextureView textureView;
    private boolean takingPicture;
    private String outputFilePath;
    private Uri mImagePathUri;

    public static void startActivityForResult(Activity activity) {
        Intent intent = new Intent(activity, CaptureActivity.class);
        activity.startActivityForResult(intent, Constant.REQ_CAPTURE);
    }

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mBinding = DataBindingUtil.setContentView(this, R.layout.activity_layout_capture);
        ActivityCompat.requestPermissions(this, PERMISSIONS, PERMISSION_CODE);
        mBinding.recordView.setOnRecordListener(new RecordView.onRecordListener() {
            @Override
            public void onClick() {
                takingPicture = true;
//                File file = new File(Environment.getExternalStoragePublicDirectory(
//                        Environment.DIRECTORY_DOWNLOADS), System.currentTimeMillis() + ".jpeg");
                File file = new File(getExternalFilesDir(Environment.DIRECTORY_PICTURES),
                        System.currentTimeMillis() + ".jpeg");
//                File file = new File(MediaStoreUtils.getFilePath(false));
//                ContentValues contentValues = MediaStoreUtils.getImageContentValues();
                mBinding.captureTips.setVisibility(View.INVISIBLE);
                imageCapture.takePicture(file, new ImageCapture.OnImageSavedListener() {
                    @Override
                    public void onImageSaved(@NonNull File file) {
                        onFileSaved(file);
                    }

                    @Override
                    public void onError(@NonNull ImageCapture.UseCaseError useCaseError, @NonNull String message, @Nullable Throwable cause) {
                        Log.e("takePicture",message);
                        showErrorToast(message);
                    }
                });
            }

            @SuppressLint("RestrictedApi")
            @Override
            public void onLongClick() {
                takingPicture = false;
//                File file = new File(Environment.getExternalStoragePublicDirectory(
//                        Environment.DIRECTORY_DOWNLOADS), System.currentTimeMillis() + ".mp4");
                File file = new File(getExternalFilesDir(Environment.DIRECTORY_PICTURES),
                        System.currentTimeMillis() + ".mp4");
                videoCapture.startRecording(file, new VideoCapture.OnVideoSavedListener() {
                    @Override
                    public void onVideoSaved(File file) {
                        onFileSaved(file);
                    }

                    @Override
                    public void onError(VideoCapture.UseCaseError useCaseError, String message, @Nullable Throwable cause) {
                        Log.e("startRecording",message);
                        showErrorToast(message);
                    }
                });
            }

            @SuppressLint("RestrictedApi")
            @Override
            public void onFinish() {
                videoCapture.stopRecording();
            }
        });
    }

    private void showErrorToast(@NonNull String message) {
        if (Looper.myLooper() == Looper.getMainLooper()) {
            Toast.makeText(CaptureActivity.this, message, Toast.LENGTH_SHORT).show();
        } else {
            runOnUiThread(() -> Toast.makeText(CaptureActivity.this, message, Toast.LENGTH_SHORT).show());
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == Constant.REQ_PREVIEW && resultCode == RESULT_OK) {
            Intent intent = new Intent();
            intent.putExtra(Constant.RESULT_FILE_PATH, outputFilePath);
            //当设备处于竖屏情况时，宽高的值 需要互换，横屏不需要
            intent.putExtra(Constant.RESULT_FILE_WIDTH, resolution.getHeight());
            intent.putExtra(Constant.RESULT_FILE_HEIGHT, resolution.getWidth());
            intent.putExtra(Constant.RESULT_FILE_TYPE, !takingPicture);
            intent.putExtra(Constant.RESULT_FILE_URI, mImagePathUri);
            setResult(RESULT_OK, intent);
            finish();
        }
    }

    private void onFileSaved(File file) {
        outputFilePath = file.getAbsolutePath();
        String mimeType = takingPicture ? "image/jpeg" : "video/mp4";
        mImagePathUri = Uri.fromFile(file);
        MediaScannerConnection.scanFile(this, new String[]{outputFilePath}, new String[]{mimeType}, null);
//        PreviewActivity.startActivityForResult(this, outputFilePath, !takingPicture, "完成");
        PreviewActivity.startActivityForResult(this, mImagePathUri, outputFilePath, !takingPicture, "完成");
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == PERMISSION_CODE) {
            deniedPermission.clear();
            for (int i = 0; i < permissions.length; i++) {
                String permission = permissions[i];
                int result = grantResults[i];
                if (result != PackageManager.PERMISSION_GRANTED) {
                    deniedPermission.add(permission);
                }
            }

            if (deniedPermission.isEmpty()) {
                bindCameraX();
            } else {
                new AlertDialog.Builder(this)
                        .setMessage(getString(R.string.capture_permission_message))
                        .setNegativeButton(getString(R.string.capture_permission_no), new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                dialog.dismiss();
                                CaptureActivity.this.finish();
                            }
                        })
                        .setPositiveButton(getString(R.string.capture_permission_ok), new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                String[] denied = new String[deniedPermission.size()];
                                ActivityCompat.requestPermissions(CaptureActivity.this, deniedPermission.toArray(denied), PERMISSION_CODE);
                            }
                        }).create().show();
            }
        }
    }

    @SuppressLint("RestrictedApi")
    private void bindCameraX() {
        CameraX.unbindAll();

        //查询一下当前要使用的设备摄像头(比如后置摄像头)是否存在
        boolean hasAvailableCameraId = false;
        try {
            hasAvailableCameraId = CameraX.hasCameraWithLensFacing(mLensFacing);
        } catch (CameraInfoUnavailableException e) {
            e.printStackTrace();
        }

        if (!hasAvailableCameraId) {
            showErrorToast("无可用的设备cameraId!,请检查设备的相机是否被占用");
            finish();
            return;
        }

        //查询一下是否存在可用的cameraId.形式如：后置："0"，前置："1"
        String cameraIdForLensFacing = null;
        try {
            cameraIdForLensFacing = CameraX.getCameraFactory().cameraIdForLensFacing(mLensFacing);
        } catch (CameraInfoUnavailableException e) {
            e.printStackTrace();
        }
        if (TextUtils.isEmpty(cameraIdForLensFacing)) {
            showErrorToast("无可用的设备cameraId!,请检查设备的相机是否被占用");
            finish();
            return;
        }

        PreviewConfig config = new PreviewConfig.Builder()
                //前后摄像头
                .setLensFacing(mLensFacing)
                //旋转角度
                .setTargetRotation(rotation)
                //分辨率
                .setTargetResolution(resolution)
                //宽高比
                .setTargetAspectRatio(rational)
                .build();
        preview = new Preview(config);

        imageCapture = new ImageCapture(new ImageCaptureConfig.Builder()
                .setTargetAspectRatio(rational)
                .setTargetResolution(resolution)
                .setLensFacing(mLensFacing)
                .setTargetRotation(rotation).build());

        videoCapture = new VideoCapture(new VideoCaptureConfig.Builder()
                .setTargetRotation(rotation)
                .setLensFacing(mLensFacing)
                .setTargetResolution(resolution)
                .setTargetAspectRatio(rational)
                //视频帧率
                .setVideoFrameRate(25)
                //bit率
                .setBitRate(3 * 1024 * 1024).build());
        preview.setOnPreviewOutputUpdateListener(new Preview.OnPreviewOutputUpdateListener() {
            @Override
            public void onUpdated(Preview.PreviewOutput output) {

                textureView = mBinding.textureView;
                ViewGroup parent = (ViewGroup) textureView.getParent();
                parent.removeView(textureView);
                parent.addView(textureView, 0);

                textureView.setSurfaceTexture(output.getSurfaceTexture());
            }
        });

        //上面配置的都是我们期望的分辨率
        List<UseCase> newUseList = new ArrayList<>();
        newUseList.add(preview);
        newUseList.add(imageCapture);
        newUseList.add(videoCapture);
        //下面我们要查询一下 当前设备它所支持的分辨率有哪些，然后再更新一下 所配置的几个usecase
        Map<UseCase, Size> resolutions = CameraX.getSurfaceManager().getSuggestedResolutions(
                cameraIdForLensFacing, null, newUseList);
        Iterator<Map.Entry<UseCase, Size>> iterator = resolutions.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<UseCase, Size> next = iterator.next();
            UseCase useCase = next.getKey();
            Size value = next.getValue();
            Map<String, Size> update = new HashMap<>();
            update.put(cameraIdForLensFacing, value);
            useCase.updateSuggestedResolution(update);
        }
        CameraX.bindToLifecycle(this, preview, imageCapture, videoCapture);
    }

    @Override
    protected void onDestroy() {
        CameraX.unbindAll();
        super.onDestroy();
    }
}
/*public class CaptureActivity extends AppCompatActivity {
    private static final int CHANGE_TYPE_RATIO = 0;
    private static final int CHANGE_TYPE_SELECTOR = 1;
    private static final int CHANGE_TYPE_FLASH_MODE = 2;

    private ActivityLayoutCaptureBinding mBinding;
    private static final String[] PERMISSIONS = new String[]{Manifest.permission.CAMERA,
            Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.RECORD_AUDIO};
    private ArrayList<String> deniedPermission = new ArrayList<>(); // 如果拒绝了授权，放到这个列表里面
    private String outputFilePath; // 保存文件的地址
    private boolean takingPicture; // 是拍照还是视频，true是拍照
    private Size resolution = new Size(720, 1280); // 屏幕像素

    private ListenableFuture<ProcessCameraProvider> cameraProviderFuture;
    private ProcessCameraProvider mCameraProvider;
    private Preview mPreview;
    private ImageCapture mImageCapture;
    private VideoCapture mVideoCapture;
    private ImageAnalysis mImageAnalysis;
    private Executor executor;
    private CameraInfo mCameraInfo;
    private CameraControl mCameraControl;
    private CameraSelector mCameraSelector;
    private CameraConfig cameraConfig;
    private Uri mImagePathUri; //左下角图片uri
    ContentValues contentValues;
    private boolean mIsNextAnalysis = true; //是否分析下一张图片
    private String mQrText = "";

    public static void startActivityForResult(Activity activity) {
        Intent intent = new Intent(activity, CaptureActivity.class);
        activity.startActivityForResult(intent, Constant.REQ_CAPTURE);
    }

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        cameraConfig = new CameraConfig();
        mBinding = DataBindingUtil.setContentView(this, R.layout.activity_layout_capture);
        mBinding.setConfig(cameraConfig);

        executor = ContextCompat.getMainExecutor(this);

        ActivityCompat.requestPermissions(this, PERMISSIONS, Constant.CAPTURE_PERMISSION_CODE);

        initListener();
    }

    private void initListener() {
        mBinding.recordView.setOnRecordListener(new RecordView.onRecordListener() {
            @Override
            public void onClick() {
                takingPicture = true;
//                File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
//                        System.currentTimeMillis() + ".jpeg");
                mBinding.captureTips.setVisibility(View.INVISIBLE);
                contentValues = MediaStoreUtils.getImageContentValues();
                ImageCapture.OutputFileOptions outputFileOptions =
                        new ImageCapture.OutputFileOptions.Builder(getContentResolver(),
                                MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues).
                                build();
                mImageCapture.takePicture(outputFileOptions, executor,
                        new ImageCapture.OnImageSavedCallback() {
                            @Override
                            public void onImageSaved(@NonNull ImageCapture.OutputFileResults outputFileResults) {
                                Log.e("takePicture", Thread.currentThread().getName());
                                mImagePathUri = outputFileResults.getSavedUri();
                                mBinding.showImage.setImageURI(mImagePathUri);
//                                onFileSaved(UriUtils.uri2File(mImagePathUri));
//                                onFileSaved(FileUtils.getFilePathByUri(CaptureActivity.this, mImagePathUri));
//                                onFileSaved(FileUtils.getRealPathFromUri(CaptureActivity.this, mImagePathUri));

//                                CaptureActivity.this.getContentResolver().insert(
//                                        MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
                                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                                    onFileSaved(contentValues.getAsString(MediaStore.MediaColumns.RELATIVE_PATH));
                                } else {
                                    onFileSaved(contentValues.getAsString(MediaStore.MediaColumns.DATA));
                                }
                            }

                            @Override
                            public void onError(@NonNull ImageCaptureException exception) {
                                String msg = "图片保存失败:";
                                if (exception != null) {
                                    msg = msg + exception + exception.getMessage();
                                }
                                ToastUtils.showToast(msg);
                                Log.e("takePicture", msg);
                            }
                        }
                );
            }

            @SuppressLint("RestrictedApi")
            @Override
            public void onLongClick() {
                takingPicture = false;
//                File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
//                        System.currentTimeMillis() + ".mp4");
                mBinding.captureTips.setVisibility(View.INVISIBLE);
                contentValues = MediaStoreUtils.getVideoContentValues();
                VideoCapture.OutputFileOptions outputFileOptions =
                        new VideoCapture.OutputFileOptions.Builder(getContentResolver(),
                                MediaStore.Video.Media.EXTERNAL_CONTENT_URI, contentValues).
                                build();
                mVideoCapture.startRecording(outputFileOptions, executor, new VideoCapture.OnVideoSavedCallback() {
                    @Override
                    public void onVideoSaved(@NonNull VideoCapture.OutputFileResults outputFileResults) {
                        mImagePathUri = outputFileResults.getSavedUri();
//                        mBinding.showImage.setImageURI(mImagePathUri);
//                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
//                            onFileSaved(contentValues.getAsString(MediaStore.MediaColumns.RELATIVE_PATH));
//                        } else {
//                            onFileSaved(contentValues.getAsString(MediaStore.MediaColumns.DATA));
//                        }
                    }

                    @Override
                    public void onError(int videoCaptureError, @NonNull String message, @Nullable Throwable cause) {
                        String msg = "视频保存失败:";
                        msg = msg + message ;
                        if (cause != null) {
                            msg = msg + cause.getMessage();
                        }
                        Log.e("startRecording", msg);
                        ToastUtils.showToast(msg);

                    }
                });
            }

            @Override
            public void onFinish() {
                mBinding.captureTips.setVisibility(View.VISIBLE);
            }
        });

        mBinding.facing.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                cameraConfig.setmFacing(cameraConfig.getmFacing());
                changeCameraConfig(CHANGE_TYPE_SELECTOR);
            }
        });
        mBinding.flashMode.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                cameraConfig.setmFlashMode(cameraConfig.getmFlashMode());
                changeCameraConfig(CHANGE_TYPE_FLASH_MODE);
            }
        });
        mBinding.ratio.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                cameraConfig.setmRatio(cameraConfig.getmRatio());
                changeCameraConfig(CHANGE_TYPE_RATIO);
            }
        });

        mBinding.showImage.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
//                if (mImagePathUri != null) {
//                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
//                        onFileSaved(contentValues.getAsString(MediaStore.MediaColumns.RELATIVE_PATH));
//                    } else {
//                        onFileSaved(contentValues.getAsString(MediaStore.MediaColumns.DATA));
//                    }
//                }
            }
        });
    }

    private void changeCameraConfig(int changeType) {
        if (changeType == CHANGE_TYPE_RATIO) {
            resetImageCapture();
        } else if (changeType == CHANGE_TYPE_FLASH_MODE) {
            resetImageCapture();
        } else if (changeType == CHANGE_TYPE_SELECTOR) {
            initCamera();
        }
    }

    public void resetImageCapture() {
        if (mCameraProvider.isBound(mImageCapture)) {
            mCameraProvider.unbind(mImageCapture);
        }
        initImageCapture();
        mCameraProvider.bindToLifecycle(this, mCameraSelector, mImageCapture);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == Constant.REQ_PREVIEW && resultCode == RESULT_OK) {
            Intent intent = new Intent();
            intent.putExtra(Constant.RESULT_FILE_PATH, outputFilePath);
            //当设备处于竖屏情况时，宽高的值 需要互换，横屏不需要
            intent.putExtra(Constant.RESULT_FILE_WIDTH, resolution.getHeight());
            intent.putExtra(Constant.RESULT_FILE_HEIGHT, resolution.getWidth());
            intent.putExtra(Constant.RESULT_FILE_TYPE, !takingPicture);
            intent.putExtra(Constant.RESULT_FILE_URI, mImagePathUri);
            setResult(RESULT_OK, intent);
            finish();
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == Constant.CAPTURE_PERMISSION_CODE) {
            deniedPermission.clear();
            for (int i = 0; i < permissions.length; i++) {
                String permission = permissions[i];
                int result = grantResults[i];
                if (result != PackageManager.PERMISSION_GRANTED) {
                    deniedPermission.add(permission);
                }
            }

            if (deniedPermission.isEmpty()) {
                initCamera();
            } else {
                new AlertDialog.Builder(this)
                        .setMessage(getString(R.string.capture_permission_message))
                        .setNegativeButton(getString(R.string.capture_permission_no), new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                dialog.dismiss();
                                CaptureActivity.this.finish();
                            }
                        })
                        .setPositiveButton(getString(R.string.capture_permission_ok), new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                String[] denied = new String[deniedPermission.size()];
                                ActivityCompat.requestPermissions(CaptureActivity.this,
                                        deniedPermission.toArray(denied), Constant.CAPTURE_PERMISSION_CODE);
                            }
                        }).create().show();
            }
        }
    }

    private void initCamera() {
        cameraProviderFuture = ProcessCameraProvider.getInstance(this);
        initUseCases();
        cameraProviderFuture.addListener(() -> {
            try {
                mCameraProvider = cameraProviderFuture.get();
                mCameraProvider.unbindAll();
                mPreview.setSurfaceProvider(mBinding.previewView.getSurfaceProvider());
                Camera camera = mCameraProvider.bindToLifecycle(this,
                        mCameraSelector, mPreview, mImageCapture, mVideoCapture, mImageAnalysis);
                mCameraInfo = camera.getCameraInfo();
                mCameraControl = camera.getCameraControl();

            } catch (ExecutionException | InterruptedException e) {
                Log.e("initCamera", e.getMessage());
            }
        }, executor);
    }

    *//**
 * 初始化配置信息
 * <p>
 * 图像分析
 * <p>
 * 扫描二维码 https://stackoverflow.com/questions/58113159/how-to-use-zxing-with-android-camerax-to-decode-barcode-and-qr-codes
 * <p>
 * interface PlaneProxy  具有类似于Plane接口的平面代理
 * 返回行跨度。int getRowStride（）;
 * 返回像素步幅。int getPixelStride（）;
 * 返回像素缓冲区。ByteBuffer getBuffer（）;
 * <p>
 * YUV，分为三个分量，“Y”表示明亮度（Luminance或Luma），也就是灰度值；而“U”和“V”
 * 表示的则是色度（Chrominance或Chroma），作用是描述影像色彩及饱和度，用于指定像素的颜色。
 * 与我们熟知的RGB类似，YUV也是一种颜色编码方法，主要用于电视系统以及模拟视频领域，
 * 它将亮度信息（Y）与色彩信息（UV）分离，没有UV信息一样可以显示完整的图像，
 * 只不过是黑白的，这样的设计很好地解决了彩色电视机与黑白电视的兼容问题。并且，
 * YUV不像RGB那样要求三个独立的视频信号同时传输，所以用YUV方式传送占用极少的频宽。
 * ImageProxy.PlaneProxy yPlane = image.getPlanes()[0];
 * <p>
 * buffer.remaining() 返回当前位置和极限之间的元素数量。
 *
 * @return 此缓冲区中剩余的元素数
 * <p>
 * <p>
 * 构建图像预览
 * <p>
 * 选择摄像头
 *//*
    private void initUseCases() {
        initImageAnalysis();
        initImageCapture();
        initVideoCapture();
        // 视频：VideoCapture
        initPreview();
        initCameraSelector();
    }

    *//**
 * 图像分析
 *//*
    private void initImageAnalysis() {
//        if (cameraConfig.getmRatio() == AspectRatio.RATIO_4_3) {
//            resolution = new Size(720, 960);
//        } else {
//            resolution = new Size(720, 1280);
//        }

//        CameraSelector cameraSelector = new CameraSelector.Builder().
//                requireLensFacing(cameraConfig.getmFacing()).build();
        mImageAnalysis = new ImageAnalysis.Builder()
//                .setTargetAspectRatio(cameraConfig.getmRatio())
// 宽高比 Cannot use both setTargetResolution and setTargetAspectRatio on the same config.
//                .setCameraSelector(cameraSelector)
                .setTargetResolution(resolution) // 分辨率
                .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST) // 非阻塞模式
                .build();

        mImageAnalysis.setAnalyzer(executor, new ImageAnalysis.Analyzer() {
            @Override
            public void analyze(@NonNull ImageProxy image) {
                int rotationDegrees = image.getImageInfo().getRotationDegrees();
                *//**
 * 扫描二维码 https://stackoverflow.com/questions/58113159/how-to-use-zxing-with-android-camerax-to-decode-barcode-and-qr-codes
 *
 * interface PlaneProxy  具有类似于Plane接口的平面代理
 *      返回行跨度。int getRowStride（）;
 *      返回像素步幅。int getPixelStride（）;
 *      返回像素缓冲区。ByteBuffer getBuffer（）;
 *
 * YUV，分为三个分量，“Y”表示明亮度（Luminance或Luma），也就是灰度值；而“U”和“V”
 *      表示的则是色度（Chrominance或Chroma），作用是描述影像色彩及饱和度，用于指定像素的颜色。
 *      与我们熟知的RGB类似，YUV也是一种颜色编码方法，主要用于电视系统以及模拟视频领域，
 *      它将亮度信息（Y）与色彩信息（UV）分离，没有UV信息一样可以显示完整的图像，
 *      只不过是黑白的，这样的设计很好地解决了彩色电视机与黑白电视的兼容问题。并且，
 *      YUV不像RGB那样要求三个独立的视频信号同时传输，所以用YUV方式传送占用极少的频宽。
 *      ImageProxy.PlaneProxy yPlane = image.getPlanes()[0];
 *
 * buffer.remaining() 返回当前位置和极限之间的元素数量。
 *      @return 此缓冲区中剩余的元素数
 *
 *//*
                if ((image.getFormat() == ImageFormat.YUV_420_888 || image.getFormat() == ImageFormat.YUV_422_888
                        || image.getFormat() == ImageFormat.YUV_444_888) && image.getPlanes().length == 3) {
                    ByteBuffer buffer = image.getPlanes()[0].getBuffer();
                    byte[] data = new byte[buffer.remaining()];
                    buffer.get(data);

                    PlanarYUVLuminanceSource source = new PlanarYUVLuminanceSource(data, image.getWidth(),
                            image.getHeight(), 0, 0, image.getWidth(), image.getHeight(), false);
                    BinaryBitmap binaryBitmap = new BinaryBitmap(new HybridBinarizer(source));
                    try {
                        Result result = DecodeCodeTools.getDefaultMultiFormatReader().decode(binaryBitmap);
                        if (result != null && (StringUtils.isEmpty(mQrText) || !StringUtils.equals(mQrText, result.getText()))) {
                            mQrText = result.getText();
                            Log.e("camerax result:", result.toString());
                            ToastUtils.showToast(result.getText());
                            // TODO 只扫描一张
                            // mIsNextAnalysis = false;
                        }
                    } catch (Exception e) {
//                        Log.e("camerax analyze:", e.toString());
                    }
                }
                if (mIsNextAnalysis) {
                    image.close();
                }
            }

        });
    }

    *//**
 * 构建图像预览
 *//*
    private void initPreview() {
        mPreview = new Preview.Builder()
                .setTargetAspectRatio(cameraConfig.getmRatio())
                .build();
    }

    *//**
 * 选择摄像头
 *//*
    private void initCameraSelector() {
        Log.e("initCameraSelector", String.valueOf(cameraConfig.getmFacing()));
        mCameraSelector = new CameraSelector.Builder()
                .requireLensFacing(cameraConfig.getmFacing())
                .build();
    }

    @SuppressLint("RestrictedApi")
    private void initVideoCapture(){
        mVideoCapture = new VideoCapture.Builder()
//                .setTargetResolution(resolution)
                .setTargetAspectRatio(cameraConfig.getmRatio())
                .setVideoFrameRate(25)//视频帧率
                .setBitRate(3 * 1024 * 1024).build();//bit率
    }

    private void initImageCapture() {
        Log.e("initImageCapture", String.valueOf(cameraConfig.getmFlashMode()));
        // 构建图像捕获用例
        mImageCapture = new ImageCapture.Builder()
                .setFlashMode(cameraConfig.getmFlashMode())
                .setTargetAspectRatio(cameraConfig.getmRatio())
                .setCaptureMode(ImageCapture.CAPTURE_MODE_MAXIMIZE_QUALITY)
                .build();
        // 旋转监听
        OrientationEventListener orientationEventListener = new OrientationEventListener(this) {
            @Override
            public void onOrientationChanged(int orientation) {
                int rotation;
                // Monitors orientation values to determine the target rotation value
                if (orientation >= 45 && orientation < 135) {
                    rotation = Surface.ROTATION_270;
                } else if (orientation >= 135 && orientation < 225) {
                    rotation = Surface.ROTATION_180;
                } else if (orientation >= 225 && orientation < 315) {
                    rotation = Surface.ROTATION_90;
                } else {
                    rotation = Surface.ROTATION_0;
                }
                mImageCapture.setTargetRotation(rotation);
            }
        };
        orientationEventListener.enable();
    }

//    private void onFileSaved(File file) {
//        outputFilePath = file.getAbsolutePath();
//        String mimeType = takingPicture ? "image/jpeg" : "video/mp4";
//        MediaScannerConnection.scanFile(this, new String[]{outputFilePath}, new String[]{mimeType}, null);
//        PreviewActivity.startActivityForResult(this, mImagePathUri, outputFilePath, !takingPicture, "完成");
//    }

    private void onFileSaved(String s) {
        outputFilePath = s;
        Log.e("onFileSaved:", outputFilePath + " takingPicture:" + takingPicture);
        String mimeType = takingPicture ? "image/jpeg" : "video/mp4";
        MediaScannerConnection.scanFile(this, new String[]{outputFilePath}, new String[]{mimeType}, null);

        PreviewActivity.startActivityForResult(this, mImagePathUri, outputFilePath, !takingPicture, "完成");
    }

//    private void showToast(@NonNull String message) {
//        if (Looper.myLooper() == Looper.getMainLooper()) {
//            Toast.makeText(CaptureActivity.this, message, Toast.LENGTH_SHORT).show();
//        } else {
//            runOnUiThread(() -> Toast.makeText(CaptureActivity.this, message, Toast.LENGTH_SHORT).show());
//        }
//    }
}*/


